package cn.jsprun.struts.foreg.actions;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResources;

import cn.jsprun.domain.Members;
import cn.jsprun.domain.Searchindex;
import cn.jsprun.domain.Threadtypes;
import cn.jsprun.struts.action.BaseAction;
import cn.jsprun.utils.Common;

public class SearchThreadAction extends BaseAction {
	@SuppressWarnings("unused")
	private static int convertInt(String s) {
		int count = 0;
		try {
			count = Integer.valueOf(s);
		} catch (Exception e) {
		}
		return count;
	}

	@SuppressWarnings("unchecked")
	public ActionForward toSearch(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {
		Map<String,String> usergroups = (Map<String,String>)request.getAttribute("usergroups");
		if(usergroups==null || convertInt(usergroups.get("allowsearch"))<=0){
			request.setAttribute("show_message", getMessage(request, "group_nopermission",usergroups.get("grouptitle")));
			return mapping.findForward("nopermission");
		}
		HttpSession session=request.getSession();
		short groupid = (Short)session.getAttribute("jsprun_groupid");
		Members member = (Members)session.getAttribute("user");
		request.setAttribute("forumselect", Common.forumselect(false, false,groupid,member!=null?member.getExtgroupids():"",null,false));
		ServletContext context=servlet.getServletContext();
		Map<String, String> settings = (Map<String, String>) context.getAttribute("settings");
		String hottaglist = "";
		if(settings.get("tagstatus").equals("1")){
			List<Map<String,String>> taglist = dataBaseService.executeQuery("SELECT tagname FROM jrun_tags WHERE closed=0 ORDER BY total DESC LIMIT 5");
			for(Map<String,String> tags:taglist){
				String tag = "<a href=\"tag.jsp?name="+Common.encode(tags.get("tagname"))+"\" target=\"_blank\">"+tags.get("tagname")+"</a>";
				hottaglist = hottaglist+"&nbsp;"+tag;
			}
			taglist = null;
		}
		request.setAttribute("hottaglist", hottaglist);
		return mapping.findForward("tosearch");
	}
	@SuppressWarnings("unchecked")
	public ActionForward toSearchByType(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {
		Map<String,String>usergroups = (Map<String,String>)request.getAttribute("usergroups");
		if(usergroups==null || usergroups.get("allowsearch").equals("0")){
			request.setAttribute("show_message", getMessage(request, "group_nopermission",usergroups.get("grouptitle")));
			return mapping.findForward("nopermission");
		}
		HttpSession session=request.getSession();
		short groupid = (Short)session.getAttribute("jsprun_groupid");
		Members member = (Members)session.getAttribute("user");
		request.setAttribute("forumselect", Common.forumselect(false, false,groupid,member!=null?member.getExtgroupids():"",null,false));
		String typehql = "from Threadtypes as t where t.special='1' order by displayorder";
		List<Threadtypes> typelist = searchService.findThreadtypeByHql(typehql);
		request.setAttribute("threadtype", typelist);
		request.setAttribute("typeid", request.getParameter("typeid"));
		return mapping.findForward("tosearchbytype");
	}
	@SuppressWarnings("unchecked")
	public ActionForward search(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {
		ServletContext context=servlet.getServletContext();
		Map<String, String> settings = (Map<String, String>) context.getAttribute("settings");
		Map<String,String> forumStr = (Map<String,String>)request.getAttribute("forums");
		Map<String,String> usergroups = (Map<String,String>)request.getAttribute("usergroups");
		if(usergroups==null || usergroups.get("allowsearch").equals("0")){
			request.setAttribute("show_message", getMessage(request, "group_nopermission",usergroups.get("grouptitle")));
			return mapping.findForward("nopermission");
		}
		Map<String,Map<String,String>> forumMap=dataParse.characterParse(forumStr.get("forums"),false);
		request.setAttribute("threadsticky", settings.get("threadsticky").split(","));
		String srchtxt = request.getParameter("srchtxt"); 
		String srchuname = request.getParameter("srchuname");  
		HttpSession session = request.getSession();
		int uid = (Integer)session.getAttribute("jsprun_uid");
		short groupid = (Short)session.getAttribute("jsprun_groupid");
		Members member = (Members)session.getAttribute("user");
		int cachelife_text = 3600;
		int timestamp = (Integer)(request.getAttribute("timestamp"));
		String searchid = request.getParameter("searchid");
		String orderby = request.getParameter("orderby");
		String ascdesc = request.getParameter("ascdesc");
		orderby = Common.in_array(new String[]{"dateline","replies","views"},orderby)?orderby:"lastpost";
		ascdesc = !Common.empty(ascdesc)&&ascdesc.equals("asc")?"asc":"desc";
		if (searchid != null && !searchid.equals("")) {
			List<Map<String,String>> searchindex = dataBaseService.executeQuery("select tids from jrun_searchindex as i where i.searchid="+searchid);
			if(searchindex!=null && searchindex.size()>0){
			String tids = searchindex.get(0).get("tids");
			if (tids.equals("0")) {
				request.setAttribute("threadlist", null);
			} else {
				int size = Common.toDigit(dataBaseService.executeQuery("select count(*) as count from jrun_threads as t where t.tid in ("+tids+") and t.displayorder>='0'").get(0).get("count"));
				int tpp = member != null && member.getTpp() > 0 ? member.getTpp(): Integer.valueOf(settings.get("topicperpage"));
				int page =Math.max(Common.intval(request.getParameter("page")), 1);
				Map<String,Integer> multiInfo=Common.getMultiInfo(size, tpp, page);
				page=multiInfo.get("curpage");
				int start_limit=multiInfo.get("start_limit");
				String url = "search.jsp?action=search&searchid=" + searchid + "&orderby=" + orderby + "&ascdesc=" + ascdesc;
				Map<String,Object> multi=Common.multi(size, tpp, page, url,0, 10, true, false, null, false);
				request.setAttribute("multi", multi);
				String hql = "SELECT t.*,f.name FROM jrun_threads as t LEFT JOIN jrun_forums as f on t.fid=f.fid where t.tid IN ( "+tids+" ) AND t.displayorder>='0' order by " + orderby + " " + ascdesc+" limit "+start_limit+","+tpp;
				List<Map<String,String>> disgetThread = dataBaseService.executeQuery(hql);
				if (disgetThread != null) {
					int ppp = member != null&& member.getPpp() > 0 ? member.getPpp() : Integer.valueOf(settings.get("postperpage"));
					for (Map<String,String> thread : disgetThread) {
						Common.procThread(thread, ppp);
					}
					request.setAttribute("threadlist", disgetThread);
				} else {
					request.setAttribute("threadlist", null);
				}
			}
			}else{
				request.setAttribute("threadlist", null);
			}
			if(Common.isshowsuccess(session, "search_redirect")){
				return mapping.findForward("searchresult");
			}else if(request.getParameter("path")==null && request.getParameter("page")==null){
				request.setAttribute("successInfo", getMessage(request, "search_redirect"));
				request.setAttribute("requestPath", "search.jsp?action=search&searchid=" + searchid+ "&orderby=" + orderby + "&ascdesc=" + ascdesc+"&path=1");
				return mapping.findForward("showMessage");
			}else{
				return mapping.findForward("searchresult");
			}
		} else {
			String messages = null;
			Map creditspolicys=dataParse.characterParse(settings.get("creditspolicy"),false);
			Map<Integer, Integer> postcredits=(Map<Integer,Integer>)creditspolicys.get("search");
			Map extcredits = dataParse.characterParse(settings.get("extcredits"), true);
			Set<Integer> keys = postcredits.keySet();
			for (Integer key : keys) {
				Map extcreditmap = (Map)extcredits.get(key);
				if(extcreditmap!=null){
					int extcredit = member==null?0:(Integer)Common.getValues(member, "extcredits"+key);
					int getattacreditvalue = Integer.valueOf(postcredits.get(key)+"");
					String lowerlimit = extcreditmap.get("lowerlimit")==null?"0":String.valueOf(extcreditmap.get("lowerlimit"));
					if(getattacreditvalue!=0&&extcredit-getattacreditvalue<=Integer.valueOf(lowerlimit)){
						String unit = extcreditmap.get("unit")!=null?"":extcreditmap.get("unit").toString();
						String title = extcreditmap.get("title")!=null?"":extcreditmap.get("title").toString();
						messages =  getMessage(request, "credits_policy_num_lowerlimit", title,lowerlimit,unit);;
						break;
					}
				}
			}
			if(messages!=null){
				request.setAttribute("errorInfo", messages);
				return mapping.findForward("showMessage");
			}
			if(uid!=0){
				Common.updatepostcredits("-", uid, postcredits);
				Common.updatepostcredits(uid, settings.get("creditsformula"));
			}
			String searchctrl = settings.get("searchctrl");  
			String maxspm = settings.get("maxspm"); 
			String maxsearchresult = settings.get("maxsearchresults");  
			String special[] = request.getParameterValues("special[]"); 
			String srchfrom = request.getParameter("srchfrom"); 
			String srchfid[] = request.getParameterValues("srchfid"); 
			String srchtype = request.getParameter("srchtype"); 
			 String srchfilter = request.getParameter("srchfilter"); 
			String before = request.getParameter("before"); 
			srchtype = srchtype==null?"":srchtype;
			srchfilter = srchfilter==null?"":srchfilter;
			before = before == null?"0":before;
			if(usergroups.get("allowsearch").equals("2")&& srchtype.equals("fulltext")) {
				
				MessageResources resources = getResources(request);
				Locale locale = getLocale(request);
				
				String message=Common.periodscheck(settings.get("searchbanperiods"), Byte.valueOf(usergroups.get("disableperiodctrl")),timestamp,settings.get("timeoffset"),resources,locale);
				if(message!=null)
				{
					request.setAttribute("show_message", message);
					return mapping.findForward("nopermission");
				}
			} else if(!srchtype.equals("title")||!srchtype.equals("blog")) {
				srchtype = "title";
			}
			String srchuid = request.getParameter("srchuid");
			if(Common.empty(srchtxt) && Common.empty(srchuid) && Common.empty(srchuname) && Common.empty(srchfrom) && !Common.in_array(new String[]{"digest","top"}, srchfilter) && Common.empty(special)) {
				request.setAttribute("errorInfo", getMessage(request, "search_invalid"));
				return mapping.findForward("showMessage");
			}
			srchtxt = srchtxt == null ? "" : srchtxt;
			srchuname = srchuname == null ? "" : srchuname;
			String space = "";
			if (special != null) {
				for (int i = 0; i < special.length; i++) {
					space += special[i] + ",";
				}
			}
			if (!space.equals("")) {
				space = space.substring(0, space.length() - 1);
			}
			StringBuffer forums =new StringBuffer();
			if (srchfid == null || srchfid[0].trim().equals("all")) {
				Set<String> fids = forumMap.keySet();
				String extgroupids = member!=null?member.getExtgroupids():"";
				for(String fid:fids){
					Map<String,String> forum = forumMap.get(fid);
					if ((forum.get("viewperm").equals(""))||Common.forumperm(forum.get("viewperm"), groupid, extgroupids)) {
						forums.append(fid + ",");
					}
				}
			} else {
				for (int i = 0; i < srchfid.length; i++) {
					forums.append(srchfid[i] + ",");
				}
			}
			if (forums.length()>0) {
				forums.deleteCharAt(forums.length()-1);
			}
			if(forums.toString().equals("all")){
				forums.delete(0, forums.length());
			}
			if(srchuid==null){
				srchuid = "0";
			}
			String searchstring = srchtype + "|" + srchtxt + "|"+srchuid+"|" + srchuname+ "|" + forums + "|" + srchfrom + "|" + before + "|"+ srchfilter + "|" + special;
			String searchindexhql = "select s.searchid from jrun_searchindex as s where s.searchstring = '"+ Common.addslashes(searchstring) + "' and s.expiration >" + timestamp;
			List<Map<String,String>> searchindex = dataBaseService.executeQuery(searchindexhql);
			if (searchindex != null && searchindex.size()>0) {
				try {
					response.sendRedirect("search.jsp?action=search&searchid="+searchindex.get(0).get("searchid")+"&orderby="+orderby+"&ascdesc="+ascdesc);
				} catch (IOException e) {
				}
				return null;
			} else { 
				String ip = Common.get_onlineip(request);
				if (!searchctrl.equals("0")) {
					int times = timestamp - convertInt(searchctrl);
					String ctrlhql = "select searchid from jrun_searchindex as s where s.useip='"+ ip + "' and uid=" + uid + " and s.dateline >="+ times+" limit 1";
					List<Map<String,String>> index = dataBaseService.executeQuery(ctrlhql);
					if (index != null && index.size()>0) {
						String message = getMessage(request, "search_ctrl", searchctrl);
						request.setAttribute("errorInfo", message);
						return mapping.findForward("showMessage");
					}
					index = null;
				}
				if (!maxspm.equals("0")) {
					int times = timestamp - 60;
					String maxhql = "select count(*) from Searchindex as s where s.useip='" + ip + "' and uid=" + uid + " and s.dateline>=" + times;
					int count = searchService.findseachindexcountbyHql(maxhql);
					if (count >= convertInt(maxspm)) {
						String message = getMessage(request, "search_toomany", maxspm);
						request.setAttribute("errorInfo", message);
						return mapping.findForward("showMessage");
					}
				}
				StringBuffer threadhql = new StringBuffer();
				if (srchtype.equals("fulltext")) {
					threadhql.append("select t.tid from jrun_threads as t left join jrun_posts as p on t.tid=p.tid where t.displayorder>='0' and ");
				} else {
					threadhql.append("select t.tid from jrun_threads as t where t.displayorder>='0' and ");
				}
				if (!srchtxt.equals("")) { 
					srchtxt = srchtxt.replaceAll("\\*", "%");
					srchtxt = srchtxt.toLowerCase();
					if (Common.matches(srchtxt,"[and|\\+|&|\\s+]") && !Common.matches(srchtxt,"[or|\\|]")) {
						srchtxt = srchtxt.replaceAll("( and |&| )", "+");
						String[] keyword = srchtxt.split("\\+");
						for (int i = 0; i < keyword.length; i++) {
							if (srchtype.equals("fulltext")) {
								threadhql.append("p.message like '%" + Common.addslashes(keyword[i].trim())+ "%' and ");
							} else {
								threadhql.append("t.subject like '%" + Common.addslashes(keyword[i].trim())+ "%' and ");
							}
						}
					} else {
						srchtxt = srchtxt.replaceAll("( or |\\|)", "+");
						String[] keyword = srchtxt.split("\\+");
						if(srchtype.equals("fulltext")){
							threadhql.append("(");
							for (int i = 0; i < keyword.length; i++) {
								threadhql.append("p.message like '%" + Common.addslashes(keyword[i].trim())+ "%' or ");
							}
						}else{
							threadhql.append("(");
							for (int i = 0; i < keyword.length; i++) {
								threadhql.append("t.subject like '%" + Common.addslashes(keyword[i].trim())+ "%' or ");
							}
						}
					}
				}
				int lastor = threadhql.lastIndexOf("or ");
				if (lastor > 0) {
					threadhql.delete(lastor, threadhql.length());
					threadhql.append(") and ");
				}
				if (!srchuname.equals("")) {  
					StringBuffer uids = new StringBuffer("0");
					srchuname = srchuname.replaceAll("\\*", "%");
					String memhql = "select uid from jrun_members as m where m.username like '"+ Common.addslashes(srchuname.trim()) + "' limit 0,50";
					List<Map<String,String>> memberlist = dataBaseService.executeQuery(memhql);
					if (memberlist != null && memberlist.size() > 0) {
						for (Map<String,String> members : memberlist) {
							uids.append(","+members.get("uid"));
						}
					}
					if (srchtype.equals("fulltext")) {
						threadhql.append("p.authorid in ( " + uids + " ) and ");
					} else {
						threadhql.append("t.authorid in ( " + uids + " ) and ");
					}
				}
				if(srchuid!=null && !srchuid.equals("0")){
					threadhql.append("t.authorid="+srchuid+" and ");
				}
				if (srchtype.equals("blog")) {
					threadhql.append("t.blog=1 and ");
				} else if (srchtype.equals("trade")) {
					threadhql.append("t.special=2 and ");
				}
				if (srchfilter.equals("digest")) {
					threadhql.append("t.digest > 0 and ");
				} else if (srchfilter.equals("top")) {
					threadhql.append("t.displayorder > 0 and ");
				}
				if (!space.equals("")) {
					threadhql.append("t.special in ( " + space+ " ) and ");
				}
				
				if (!forums.toString().equals("")) {
					threadhql.append("t.fid in ( " + forums.toString() + " ) and ");
				}
				if (srchfrom!=null && !srchfrom.equals("0")) {
					int datetime = timestamp- Integer.valueOf(srchfrom);
					if (before.equals("0")) {
						threadhql.append("t.lastpost >= " + datetime + " and ");
					} else {
						threadhql.append("t.lastpost <=" + datetime + " and ");
					}
				}
				int lastand = threadhql.lastIndexOf("and");
				if (lastand > 0) {
					threadhql.delete(lastand, threadhql.length());
				}
				threadhql.append("order by t." + orderby + " " + ascdesc+" limit 0,"+maxsearchresult);
				List<Map<String,String>> threadlist = dataBaseService.executeQuery(threadhql.toString());
				String tids = "0";
				int threadcount = 0;
				if (threadlist != null && threadlist.size() > 0) {
					threadcount = threadlist.size();
					for (Map<String,String> t : threadlist) {
						tids += ","+t.get("tid");
					}
				}
				threadlist = null;
				Searchindex searchdex = new Searchindex();
				searchdex.setDateline(timestamp);
				int exprtation = timestamp + cachelife_text;
				searchdex.setExpiration(exprtation);
				searchdex.setKeywords(srchtxt + "+" + srchuname);
				searchdex.setSearchstring(searchstring);
				searchdex.setThreads(Short.valueOf(threadcount + ""));
				searchdex.setThreadtypeid(Short.valueOf("0"));
				searchdex.setTids(tids);
				searchdex.setUid(uid);
				searchdex.setUseip(ip);
				int searchids = searchService.insertSearchindex(searchdex);
				try {
					response.sendRedirect("search.jsp?action=search&searchid="+searchids+"&orderby="+orderby+"&ascdesc="+ascdesc);
				} catch (IOException e) {
				}
				return null;
			}
		}
	}

	@SuppressWarnings("unchecked")
	public ActionForward searchbytype(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		Map<String,String> forumStr = (Map<String,String>)request.getAttribute("forums");
		Map<String,Map<String,String>> forumMap=dataParse.characterParse(forumStr.get("forums"),false);
		HttpSession session = request.getSession();
		Members member = (Members)session.getAttribute("user");
		short groupid = (Short)session.getAttribute("jsprun_groupid");
		int uid = (Integer) session.getAttribute("jsprun_uid");
		int cachelife_text = 3600;
		int timestamp = (Integer)(request.getAttribute("timestamp"));
		ServletContext context=servlet.getServletContext();
		Map<String, String> settings = (Map<String, String>) context.getAttribute("settings");
		String searchctrl = settings.get("searchctrl");  
		String maxspm = settings.get("maxspm"); 
		String maxsearchresult = settings.get("maxsearchresults");  
		String srchfid[] = request.getParameterValues("srchfid[]");  
		StringBuffer forums =new StringBuffer();
		if (srchfid == null || srchfid[0].trim().equals("all")) {
			Set<String> fids = forumMap.keySet();
			String extgroupids = member!=null?member.getExtgroupids():"";
			for(String fid:fids){
				Map<String,String> forum = forumMap.get(fid);
				if ((forum.get("viewperm").equals(""))||Common.forumperm(forum.get("viewperm"), groupid, extgroupids)) {
					forums.append(fid + ",");
				}
			}
		} else {
			for (int i = 0; i < srchfid.length; i++) {
				forums.append(srchfid[i] + ",");
			}
		}
		if (forums.length()>0) {
			forums.deleteCharAt(forums.length()-1);
		}
		if(forums.toString().equals("all")){
			forums.delete(0, forums.length());
		}
		String searchstring = "type|";
		String searchindexhql = "from Searchindex as s where s.searchstring = '"+ searchstring + "' and s.expiration >" + timestamp;
		Searchindex searchindex = searchService.findSearchindexByHql(searchindexhql);
		if (searchindex != null) {
			try {
				response.sendRedirect("search.jsp?searchid="+searchindex.getSearchid()+"&orderby=lastpost&ascdesc=desc");
			} catch (IOException e) {
			}
			return null;
		} else {  
			String ip = Common.get_onlineip(request);
			if (!searchctrl.equals("0")) {
				int times = timestamp- convertInt(searchctrl);
				String ctrlhql = "select searchid from jrun_searchindex as s where s.useip='"+ ip + "' and uid=" + uid + " and s.dateline >="+ times+" limit 1";
				List<Map<String,String>> index = dataBaseService.executeQuery(ctrlhql);
				if (index != null && index.size()>0) {
					String message = getMessage(request, "search_ctrl", searchctrl);
					request.setAttribute("errorInfo", message);
					return mapping.findForward("showMessage");
				}
				index = null;
			}
			if (!maxspm.equals("0")) {
				int times = timestamp - 60;
				String maxhql = "select count(*) from Searchindex as s where s.useip='" + ip + "' and uid=" + uid + " and s.dateline>=" + times;
				int count = searchService.findseachindexcountbyHql(maxhql);
				if (count >= convertInt(maxspm)) {
					String message = getMessage(request, "search_toomany", maxspm);
					request.setAttribute("errorInfo", message);
					return mapping.findForward("showMessage");
				}
			}
			String typeid = request.getParameter("typeid");
			if (typeid.equals("0")) {
				request.setAttribute("errorInfo", getMessage(request, "search_no_type"));
				return mapping.findForward("showMessage");
			}
			String hql = "select tid from jrun_threads as t where t.typeid = " + typeid + " and t.fid in ( " + forums + " ) order by lastpost desc limit 0,"+maxsearchresult;
			List<Map<String,String>> threadlist = dataBaseService.executeQuery(hql);
			String tids = "0";
			int threadcount = 0;
			if (threadlist != null && threadlist.size() > 0) {
				threadcount = threadlist.size();
				for (Map<String,String> t : threadlist) {
					tids += ","+t.get("tid");
				}
			}
			threadlist = null;
			Searchindex searchdex = new Searchindex();
			searchdex.setDateline(timestamp);
			int exprtation = timestamp + cachelife_text;
			searchdex.setExpiration(exprtation);
			searchdex.setSearchstring(searchstring);
			searchdex.setThreads(Short.valueOf(threadcount + ""));
			searchdex.setTids(tids);
			searchdex.setUid(uid);
			searchdex.setUseip(ip);
			searchdex.setKeywords("");
			searchdex.setThreadtypeid(Short.valueOf(typeid));
			int searchids = searchService.insertSearchindex(searchdex);
			try {
				response.sendRedirect("search.jsp?action=search&searchid="+searchids+"&orderby=lastpost&ascdesc=desc");
			} catch (IOException e) {
			}
			return null;
		}
	}
}
